﻿using System;
using System.Collections.Generic;
using System.Text;
using Graffiti.Core;
using System.Collections.Specialized;
using System.Web;
using System.Text.RegularExpressions;

namespace GraffitiExtras.Plugins.IPBlocker
{
    public class IPBlocker : GraffitiEvent
    {
        public string TRUSTEDIPS;
        public string BLOCKEDIPS;

        private const int textboxLines = 10;

        public override string Name
        {
            get
            {
                return "IP Blocker";
            }
        }

        public override string Description
        {
            get
            {
                return
                    "Plug-in to block all requests from specific IPs. " +
                    "Done by <a href=\"http://nayyeri.net\">Keyvan Nayyeri</a>.";
            }
        }

        public override bool IsEditable
        {
            get
            {
                return true;
            }
        }

        protected override NameValueCollection DataAsNameValueCollection()
        {
            NameValueCollection nvc = base.DataAsNameValueCollection();
            nvc["TRUSTEDIPS"] = TRUSTEDIPS;
            nvc["BLOCKEDIPS"] = BLOCKEDIPS;

            return nvc;
        }

        public override StatusType SetValues(HttpContext context, NameValueCollection nvc)
        {
            base.SetValues(context, nvc);
            TRUSTEDIPS = nvc["TRUSTEDIPS"];
            BLOCKEDIPS = nvc["BLOCKEDIPS"];
            return StatusType.Success;
        }

        protected override FormElementCollection AddFormElements()
        {
            FormElementCollection fec = new FormElementCollection();

            fec.Add(new TextAreaFormElement("TRUSTEDIPS", "Trusted IPs",
                "List trusted IPs or IP ranges in separate lines", textboxLines));
            fec.Add(new TextAreaFormElement("BLOCKEDIPS", "Blocked IPs",
                "List blocked IPs or IP ranges in separate lines", textboxLines));

            return fec;
        }


        public override void Init(GraffitiApplication ga)
        {
            ga.BeginRequest += new EventHandler(ga_BeginRequest);
        }

        void ga_BeginRequest(object sender, EventArgs e)
        {
            HttpContext context = HttpContext.Current;

            if (!context.Request.IsAuthenticated)
            {
                string clientIP = context.Request.UserHostAddress;

                if (CheckIP(clientIP))
                {
                    // Blocking process
                    context.Response.StatusCode = 200;
                    context.Response.SuppressContent = true;
                    context.Response.End();
                }
            }
        }

        private bool CheckIP(string clientIP)
        {
            try
            {
                if (Contains(TRUSTEDIPS, clientIP))
                    return false;
                else if (Contains(BLOCKEDIPS, clientIP))
                    return true;
            }
            catch
            {
            }
            return false;
        }

        private bool Contains(string list, string ip)
        {
            list = list.Replace("\n", ";");

            string[] items = list.Split(';');

            foreach (string item in items)
            {
                if (item.Contains("-"))
                {
                    string[] ranges = item.Split('-');
                    string lowerIP = ranges[0];
                    string upperIP = ranges[1];
                    if (CompareIPs.IsGreaterOrEqual(ip, lowerIP) &&
                        CompareIPs.IsLessOrEqual(ip, upperIP))
                        return true;
                }
                else
                {
                    if (ip == item)
                        return true;
                }
            }

            return false;
        }
    }
}
